<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Analysis\Controller;

use Admin\Controller\AdminActionController;
use Admin\Data\Common;
use Analysis\Form\StatisticsSearchForm;
use Carbon\Carbon;
use Doctrine\ORM\EntityManager;
use Laminas\Mvc\I18n\Translator;
use Laminas\View\Model\JsonModel;
use Sales\Entity\Order;
use Sales\Entity\OrderGoods;
use Sales\Entity\OrderGoodsReturn;
use User\Entity\User;

class IndexController extends AdminActionController
{
    private $translator;
    private $entityManager;

    public function __construct(
        Translator $translator,
        EntityManager $entityManager
    )
    {
        $this->translator       = $translator;
        $this->entityManager    = $entityManager;
    }

    /**
     * 客户统计
     * @return array|\Laminas\View\Model\ViewModel
     */
    public function indexAction()
    {
        $todayStart = Carbon::today();
        $todayEnd   = Carbon::now();
        $todayUserNum = $this->entityManager->getRepository(User::class)->findUserCount($todayStart->timestamp, $todayEnd->timestamp);

        $weekStart  = Carbon::now()->startOfWeek();
        $weekEnd    = Carbon::now()->endOfWeek();
        $weekUserNum = $this->entityManager->getRepository(User::class)->findUserCount($weekStart->timestamp, $weekEnd->timestamp);

        $monthStart = Carbon::now()->startOfMonth();
        $monthEnd   = Carbon::now()->endOfMonth();
        $monthUserNum = $this->entityManager->getRepository(User::class)->findUserCount($monthStart->timestamp, $monthEnd->timestamp);

        $userNum = $this->entityManager->getRepository(User::class)->findUserCount();

        $startTime  = $weekStart->timestamp;
        $endTime    = $weekEnd->timestamp;
        $startDate  = $weekStart;
        $endDate    = $weekEnd;
        $type       = '';
        $form = new StatisticsSearchForm();
        if($this->getRequest()->isGet()) {
            $data = $this->params()->fromQuery();
            $form->setData($data);

            $type = $data['type']??'week';
            if ($type == 'month') {
                $startTime  = $monthStart->timestamp;
                $endTime    = $monthEnd->timestamp;
                $startDate  = $monthStart;
                $endDate    = $monthEnd;
            }

            if($form->isValid()) {
                $data = $form->getData();
                if (!empty($data['startDate']) && !empty($data['endDate'])) {
                    $type      = '';
                    $startDate = Carbon::parse($data['startDate']);
                    $endDate   = Carbon::parse($data['endDate'].' 23:59:59');
                    $startTime = $startDate->timestamp;
                    $endTime   = $endDate->timestamp;
                } else $form->setData(['startDate' => '', 'endDate' => '']);
            }
        }

        $userDataCountList = $this->entityManager->getRepository(User::class)->findUserDateCount($startTime, $endTime);
        $userCountArray= [];
        if ($userDataCountList) foreach ($userDataCountList as $value) {
            $userCountArray[$value['userDate']] = $value['userNum'];
        }
        $dateArray          = [];
        $userDateCountArray = [];
        foreach (Carbon::parse($startDate)->range($endDate) as $date) {
            $dateStr    = $date->format("Y-m-d");
            $dateArray[]= "'".$dateStr."'";
            if (isset($userCountArray[$dateStr])) $userDateCountArray[$dateStr] = $userCountArray[$dateStr];
            else $userDateCountArray[$dateStr] = 0;

        }

        return [
            'form'          => $form,
            'todayUserNum'  => $todayUserNum,
            'weekUserNum'   => $weekUserNum,
            'monthUserNum'  => $monthUserNum,
            'userNum'       => $userNum,

            'type'          => $type,
            'dataStr'       => implode(',', $dateArray),
            'userStr'       => implode(',', $userDateCountArray)
        ];
    }

    /**
     * 客户排行
     * @return array
     */
    public function userRankingAction()
    {
        $page = (int) $this->params()->fromQuery('page', 1);

        $startTime  = Carbon::today()->timestamp;
        $endTime    = Carbon::now()->timestamp;
        $userGroupId= 0;
        $type       = '';
        $form = new StatisticsSearchForm();
        $form->get('userGroupId')->setValueOptions($this->userPlugin()->userGroupOptions($this->translator->translate('选择客户组')));
        if($this->getRequest()->isGet()) {
            $data = $this->params()->fromQuery();
            $form->setData($data);

            $type = $data['type']??'today';
            if ($type == 'week') {
                $startTime  = Carbon::now()->startOfWeek()->timestamp;
                $endTime    = Carbon::now()->endOfWeek()->timestamp;
            } elseif ($type == 'month') {
                $startTime  = Carbon::now()->startOfMonth()->timestamp;
                $endTime    = Carbon::now()->endOfMonth()->timestamp;
            }

            if($form->isValid()) {
                $data = $form->getData();
                if ($data['userGroupId'] > 0) $userGroupId = $data['userGroupId'];
                if (!empty($data['startDate']) && !empty($data['endDate'])) {
                    $type      = '';
                    $startTime = Carbon::parse($data['startDate'])->timestamp;
                    $endTime   = Carbon::parse($data['endDate'].' 23:59:59')->timestamp;
                } else $form->setData(['startDate' => '', 'endDate' => '']);
            }
        }

        $query      = $this->entityManager->getRepository(User::class)->findUserRanking($startTime, $endTime, $userGroupId);
        $paginator  = $this->adminCommon()->shopPaginator($query, $page);

        return [
            'type'              => $type,
            'userRankingList'   => $paginator,
            'form'              => $form,

            'startTime'         => $startTime,
            'endTime'           => $endTime
        ];
    }

    /**
     * 订单统计
     * @return array
     */
    public function orderStatisticsAction()
    {
        $todayStart = Carbon::today();
        $todayEnd   = Carbon::now();
        $todayOrderNum = $this->entityManager->getRepository(Order::class)->findOrderCount($todayStart->timestamp, $todayEnd->timestamp);

        $weekStart  = Carbon::now()->startOfWeek();
        $weekEnd    = Carbon::now()->endOfWeek();
        $weekOrderNum = $this->entityManager->getRepository(Order::class)->findOrderCount($weekStart->timestamp, $weekEnd->timestamp);

        $monthStart = Carbon::now()->startOfMonth();
        $monthEnd   = Carbon::now()->endOfMonth();
        $monthOrderNum = $this->entityManager->getRepository(Order::class)->findOrderCount($monthStart->timestamp, $monthEnd->timestamp);

        $orderNum = $this->entityManager->getRepository(Order::class)->findOrderCount();

        $startTime  = $weekStart->timestamp;
        $endTime    = $weekEnd->timestamp;
        $startDate  = $weekStart;
        $endDate    = $weekEnd;
        $userGroupId= 0;
        $type       = '';
        $form = new StatisticsSearchForm();
        $form->get('userGroupId')->setValueOptions($this->userPlugin()->userGroupOptions($this->translator->translate('选择客户组')));
        if($this->getRequest()->isGet()) {
            $data = $this->params()->fromQuery();
            $form->setData($data);

            $type = $data['type']??'week';
            if ($type == 'month') {
                $startTime  = $monthStart->timestamp;
                $endTime    = $monthEnd->timestamp;
                $startDate  = $monthStart;
                $endDate    = $monthEnd;
            }

            if($form->isValid()) {
                $data = $form->getData();
                if ($data['userGroupId'] > 0) $userGroupId = $data['userGroupId'];
                if (!empty($data['startDate']) && !empty($data['endDate'])) {
                    $type      = '';
                    $startDate = Carbon::parse($data['startDate']);
                    $endDate   = Carbon::parse($data['endDate'].' 23:59:59');
                    $startTime = $startDate->timestamp;
                    $endTime   = $endDate->timestamp;
                } else $form->setData(['startDate' => '', 'endDate' => '']);
            }
        }

        $orderDateCountList = $this->entityManager->getRepository(Order::class)->findOrderDateCountOrTotal($startTime, $endTime, $userGroupId);
        $orderCountArray= [];
        if ($orderDateCountList) foreach ($orderDateCountList as $value) {
            $orderCountArray[$value['userDate']] = $value['orderNum'];
        }
        $orderDatePayCountList = $this->entityManager->getRepository(Order::class)->findOrderDateCountOrTotal($startTime, $endTime, $userGroupId, true);
        $orderPayCountArray= [];
        if ($orderDatePayCountList) foreach ($orderDatePayCountList as $pValue) {
            $orderPayCountArray[$pValue['userDate']] = $pValue['orderNum'];
        }
        $dateArray          = [];
        $orderDateCountArray= [];
        $orderDatePayCountArray= [];
        foreach (Carbon::parse($startDate)->range($endDate) as $date) {
            $dateStr    = $date->format("Y-m-d");
            $dateArray[]= "'".$dateStr."'";
            if (isset($orderCountArray[$dateStr])) $orderDateCountArray[$dateStr] = $orderCountArray[$dateStr];
            else $orderDateCountArray[$dateStr] = 0;
            if (isset($orderPayCountArray[$dateStr])) $orderDatePayCountArray[$dateStr] = $orderPayCountArray[$dateStr];
            else $orderDatePayCountArray[$dateStr] = 0;
        }

        //支付方式统计
        $paymentList = Common::paymentList();
        $paymentArray= [];
        foreach ($paymentList AS $paymentValue) {
            $paymentArray[$paymentValue['editAction']] = "'".$paymentValue['paymentName']['content']."'";
        }
        $paymentOrder = $this->entityManager->getRepository(Order::class)->findOrderCountPayment($startTime, $endTime, $userGroupId);
        $paymentOrderCountArray = [];
        if ($paymentOrder) foreach ($paymentOrder as $pOrderValue) {
            $paymentOrderCountArray[$pOrderValue['paymentCode']] = ['name' => $paymentArray[$pOrderValue['paymentCode']], 'num' => $pOrderValue['orderNum']];
        }

        //配送统计
        $deliveryArray= Common::deliveryArray($this->translator);
        $deliveryOrder= $this->entityManager->getRepository(Order::class)->findOrderCountDelivery($startTime, $endTime, $userGroupId);
        $deliveryOrderCountArray = [];
        if ($deliveryOrder) foreach ($deliveryOrder AS $dOrderValue) {
            $deliveryOrderCountArray[$dOrderValue['deliveryType']] = ['name' => $deliveryArray[$dOrderValue['deliveryType']], 'num' => $dOrderValue['orderNum']];
        }

        return [
            'form'          => $form,
            'todayOrderNum' => $todayOrderNum,
            'weekOrderNum'  => $weekOrderNum,
            'monthOrderNum' => $monthOrderNum,
            'orderNum'      => $orderNum,

            'type'          => $type,
            'dataStr'       => implode(',', $dateArray),
            'orderStr'      => implode(',', $orderDateCountArray),
            'orderPayStr'   => implode(',', $orderDatePayCountArray),

            'paymentArray'  => $paymentArray,
            'paymentStr'    => implode(',', $paymentArray),
            'paymentOrderCountArray' => $paymentOrderCountArray,

            'deliveryArray' => $deliveryArray,
            'deliveryStr'   => '"'.implode('","', $deliveryArray).'"',
            'deliveryOrderCountArray' => $deliveryOrderCountArray
        ];
    }

    /**
     * 销售情况
     * @return array
     */
    public function salesStatisticsAction()
    {
        $todayStart = Carbon::today();
        $todayEnd   = Carbon::now();
        $todayOrderAmount = $this->entityManager->getRepository(Order::class)->findOrderTotal($todayStart->timestamp, $todayEnd->timestamp);

        $weekStart  = Carbon::now()->startOfWeek();
        $weekEnd    = Carbon::now()->endOfWeek();
        $weekOrderAmount = $this->entityManager->getRepository(Order::class)->findOrderTotal($weekStart->timestamp, $weekEnd->timestamp);

        $monthStart = Carbon::now()->startOfMonth();
        $monthEnd   = Carbon::now()->endOfMonth();
        $monthOrderAmount = $this->entityManager->getRepository(Order::class)->findOrderTotal($monthStart->timestamp, $monthEnd->timestamp);

        $orderAmount = $this->entityManager->getRepository(Order::class)->findOrderTotal();

        $startTime  = $weekStart->timestamp;
        $endTime    = $weekEnd->timestamp;
        $startDate  = $weekStart;
        $endDate    = $weekEnd;
        $userGroupId= 0;
        $type       = '';
        $form = new StatisticsSearchForm();
        $form->get('userGroupId')->setValueOptions($this->userPlugin()->userGroupOptions($this->translator->translate('选择客户组')));
        if($this->getRequest()->isGet()) {
            $data = $this->params()->fromQuery();
            $form->setData($data);

            $type = $data['type']??'week';
            if ($type == 'month') {
                $startTime  = $monthStart->timestamp;
                $endTime    = $monthEnd->timestamp;
                $startDate  = $monthStart;
                $endDate    = $monthEnd;
            }

            if($form->isValid()) {
                $data = $form->getData();
                if ($data['userGroupId'] > 0) $userGroupId = $data['userGroupId'];
                if (!empty($data['startDate']) && !empty($data['endDate'])) {
                    $type      = '';
                    $startDate = Carbon::parse($data['startDate']);
                    $endDate   = Carbon::parse($data['endDate'].' 23:59:59');
                    $startTime = $startDate->timestamp;
                    $endTime   = $endDate->timestamp;
                } else $form->setData(['startDate' => '', 'endDate' => '']);
            }
        }

        $orderAmountList    = $this->entityManager->getRepository(Order::class)->findOrderDateCountOrTotal($startTime, $endTime, $userGroupId, true, 'sum');
        $orderAmountArray   = [];
        $dateOrderAmount    = 0;
        if ($orderAmountList) foreach ($orderAmountList AS $value) {
            $orderTotalFloat = number_format($value['orderTotal'], 2, '.', '');
            $dateOrderAmount = Common::calculation($dateOrderAmount, $orderTotalFloat, 'add', 2);
            $orderAmountArray[$value['userDate']] = $orderTotalFloat;
        }

        $dateArray           = [];
        $orderDateAmountArray= [];
        foreach (Carbon::parse($startDate)->range($endDate) as $date) {
            $dateStr    = $date->format("Y-m-d");
            $dateArray[]= "'".$dateStr."'";
            if (isset($orderAmountArray[$dateStr])) $orderDateAmountArray[$dateStr] = $orderAmountArray[$dateStr];
            else $orderDateAmountArray[$dateStr] = 0;
        }

        return [
            'form'              => $form,
            'todayOrderAmount'  => $todayOrderAmount,
            'weekOrderAmount'   => $weekOrderAmount,
            'monthOrderAmount'  => $monthOrderAmount,
            'orderAmount'       => $orderAmount,
            'dateOrderAmount'   => $dateOrderAmount,

            'type'              => $type,
            'dataStr'           => implode(',', $dateArray),
            'orderAmountStr'    => implode(',', $orderDateAmountArray),
        ];
    }

    /**
     * 退款情况
     * @return array
     */
    public function returnStatisticsAction()
    {
        $todayStart = Carbon::today();
        $todayEnd   = Carbon::now();
        $todayReturnAmount = $this->entityManager->getRepository(OrderGoodsReturn::class)->findOrderReturnTotal($todayStart->timestamp, $todayEnd->timestamp);

        $weekStart  = Carbon::now()->startOfWeek();
        $weekEnd    = Carbon::now()->endOfWeek();
        $weekReturnAmount = $this->entityManager->getRepository(OrderGoodsReturn::class)->findOrderReturnTotal($weekStart->timestamp, $weekEnd->timestamp);

        $monthStart = Carbon::now()->startOfMonth();
        $monthEnd   = Carbon::now()->endOfMonth();
        $monthReturnAmount = $this->entityManager->getRepository(OrderGoodsReturn::class)->findOrderReturnTotal($monthStart->timestamp, $monthEnd->timestamp);

        $returnAmount = $this->entityManager->getRepository(OrderGoodsReturn::class)->findOrderReturnTotal();

        $startTime  = $weekStart->timestamp;
        $endTime    = $weekEnd->timestamp;
        $startDate  = $weekStart;
        $endDate    = $weekEnd;
        $userGroupId= 0;
        $type       = '';
        $form = new StatisticsSearchForm();
        $form->get('userGroupId')->setValueOptions($this->userPlugin()->userGroupOptions($this->translator->translate('选择客户组')));
        if($this->getRequest()->isGet()) {
            $data = $this->params()->fromQuery();
            $form->setData($data);

            $type = $data['type']??'week';
            if ($type == 'month') {
                $startTime  = $monthStart->timestamp;
                $endTime    = $monthEnd->timestamp;
                $startDate  = $monthStart;
                $endDate    = $monthEnd;
            }

            if($form->isValid()) {
                $data = $form->getData();
                if ($data['userGroupId'] > 0) $userGroupId = $data['userGroupId'];
                if (!empty($data['startDate']) && !empty($data['endDate'])) {
                    $type      = '';
                    $startDate = Carbon::parse($data['startDate']);
                    $endDate   = Carbon::parse($data['endDate'].' 23:59:59');
                    $startTime = $startDate->timestamp;
                    $endTime   = $endDate->timestamp;
                } else $form->setData(['startDate' => '', 'endDate' => '']);
            }
        }

        $returnAmountList    = $this->entityManager->getRepository(OrderGoodsReturn::class)->findOrderReturnDateTotal($startTime, $endTime, $userGroupId);
        $returnAmountArray   = [];
        $dateReturnAmount    = 0;
        if ($returnAmountList) foreach ($returnAmountList AS $value) {
            $orderTotalFloat = number_format($value['returnTotal'], 2, '.', '');
            $dateReturnAmount = Common::calculation($dateReturnAmount, $orderTotalFloat, 'add', 2);
            $returnAmountArray[$value['userDate']] = $orderTotalFloat;
        }

        $dateArray            = [];
        $returnDateAmountArray= [];
        foreach (Carbon::parse($startDate)->range($endDate) as $date) {
            $dateStr    = $date->format("Y-m-d");
            $dateArray[]= "'".$dateStr."'";
            if (isset($returnAmountArray[$dateStr])) $returnDateAmountArray[$dateStr] = $returnAmountArray[$dateStr];
            else $returnDateAmountArray[$dateStr] = 0;
        }

        return [
            'form'              => $form,
            'todayReturnAmount' => $todayReturnAmount,
            'weekReturnAmount'  => $weekReturnAmount,
            'monthReturnAmount' => $monthReturnAmount,
            'returnAmount'      => $returnAmount,
            'dateReturnAmount'  => $dateReturnAmount,

            'type'              => $type,
            'dataStr'           => implode(',', $dateArray),
            'returnAmountStr'   => implode(',', $returnDateAmountArray),
        ];
    }

    /**
     * 销售排行
     * @return array
     */
    public function salesRankingAction()
    {
        $page = (int) $this->params()->fromQuery('page', 1);

        $startTime  = Carbon::today()->timestamp;
        $endTime    = Carbon::now()->timestamp;
        $userGroupId= 0;
        $type       = '';

        $form = new StatisticsSearchForm();
        $form->get('userGroupId')->setValueOptions($this->userPlugin()->userGroupOptions($this->translator->translate('选择客户组')));
        if($this->getRequest()->isGet()) {
            $data = $this->params()->fromQuery();
            $form->setData($data);

            $type = $data['type'] ?? 'today';
            if ($type == 'week') {
                $startTime = Carbon::now()->startOfWeek()->timestamp;
                $endTime = Carbon::now()->endOfWeek()->timestamp;
            } elseif ($type == 'month') {
                $startTime = Carbon::now()->startOfMonth()->timestamp;
                $endTime = Carbon::now()->endOfMonth()->timestamp;
            }

            if($form->isValid()) {
                $data = $form->getData();
                if ($data['userGroupId'] > 0) $userGroupId = $data['userGroupId'];
                if (!empty($data['startDate']) && !empty($data['endDate'])) {
                    $type      = '';
                    $startTime = Carbon::parse($data['startDate'])->timestamp;
                    $endTime   = Carbon::parse($data['endDate'].' 23:59:59')->timestamp;
                } else $form->setData(['startDate' => '', 'endDate' => '']);
            }
        }

        $query      = $this->entityManager->getRepository(OrderGoods::class)->findSalesOrderGoodsRanking($startTime, $endTime, $userGroupId);
        $paginator  = $this->adminCommon()->shopPaginator($query, $page);

        return [
            'form'              => $form,
            'goodsRankingList'  => $paginator,

            'type'              => $type
        ];
    }

    /**
     * ajax获取用户订单数
     * @return JsonModel
     */
    public function ajaxUserOrderNumAction()
    {
        $userIdArray= $this->params()->fromPost('userId');
        $startTime  = (int) $this->params()->fromPost('startTime', 0);
        $endTime    = (int) $this->params()->fromPost('endTime', 0);
        if (empty($userIdArray) || $startTime <= 0 || $endTime <= 0) return new JsonModel(['state' => 'false']);

        $result = $this->entityManager->getRepository(User::class)->findUserOrderNum($startTime, $endTime, $userIdArray);
        if ($result == null) return new JsonModel(['state' => 'false']);

        return new JsonModel(['state' => 'true', 'orderNum' => $result]);
    }
}